package jp.co.nes.awssupport.compile.function;

import java.time.YearMonth;
import java.util.List;

import jp.co.nes.awssupport.access.dao.CampaignAssignedDao;
import jp.co.nes.awssupport.access.dao.MonthlyCompiledBillingDao;
import jp.co.nes.awssupport.access.dao.MonthlyCompiledBillingDao.DaoReadTypeOfTotalization;
import jp.co.nes.awssupport.business.base.AbstractRequestWithCompletionStateHandler;
import jp.co.nes.awssupport.business.bean.CommonContainerBean.ProcessingResult;
import jp.co.nes.awssupport.business.bean.CompileContainerBean;
import jp.co.nes.awssupport.business.bean.CompileInfoBean;
import jp.co.nes.awssupport.business.logic.CampaignPlanProcessing;
import jp.co.nes.awssupport.common.base.CommonException;
import jp.co.nes.awssupport.common.bean.CampaignAssignedBean;
import jp.co.nes.awssupport.common.bean.MonthlyCompiledBillingBean;
import jp.co.nes.awssupport.common.dao.ReadHandler;
import jp.co.nes.awssupport.common.dao.ReadType;
import jp.co.nes.awssupport.common.utility.BeanUtil;
import jp.co.nes.awssupport.common.utility.DateUtil;

/**
 * キャンペーンプラン適用です(Lambda)。
 */
public class CampaignPlan
        extends AbstractRequestWithCompletionStateHandler<CompileInfoBean, CompileContainerBean<CompileInfoBean>> {

    /**
     * デフォルトコンストラクタです。
     */
    public CampaignPlan() {
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.base.AbstractRequestHandler#handleRequest(java.lang.Object)
     */
    @Override
    protected CompileContainerBean<CompileInfoBean> handleRequest(CompileInfoBean input) {
        YearMonth targetYearMonth = DateUtil.toYearMonth(input.getTargetYearMonthValue());
        String linkedAccountId = input.getLinkedAccountId();

        // CampaignPlanProcessingの生成はread()メソッドの外で実行する(契約情報の取得を複数回実行しないため)
        CampaignPlanProcessing cpProcessing = new CampaignPlanProcessing(targetYearMonth);

        // 検索条件の作成
        Object[] conditions = new Object[2];
        conditions[0] = linkedAccountId;
        conditions[1] = DateUtil.toInt(targetYearMonth);

        Class<MonthlyCompiledBillingBean> cls = MonthlyCompiledBillingBean.class;
        MonthlyCompiledBillingDao dao = new MonthlyCompiledBillingDao();

        // 以下の単位で集計した内容で月次集計結果を読み込む
        // i = 0 -> 「連結アカウントID, 年月」単位
        // i = 1 -> 「連結アカウントID, 年月, 製品名」単位
        // i = 2 -> 「連結アカウントID, 年月, 使用タイプ」単位
        // i = 3 -> 「連結アカウントID, 年月, 製品名, 使用タイプ」単位
        for (int i = 0; i < 4; i++) {
            ReadType readType = getReadType(i);
            dao.read(new ReadHandler<MonthlyCompiledBillingBean>(cls, readType) {
                /*
                 * (非 Javadoc)
                 * @see jp.co.nes.awssupport.common.dao.ReadHandler#read(jp.co.nes.awssupport.common.bean.BaseBean)
                 */
                @Override
                protected void read(MonthlyCompiledBillingBean mcbBean) {
                    // キャンペーンプランを適用
                    List<CampaignAssignedBean> applyList = cpProcessing.apply(mcbBean);

                    // キャンペーン適用を削除・登録
                    CampaignAssignedDao assignedDao = new CampaignAssignedDao();
                    if (getReadType() == DaoReadTypeOfTotalization.TOTALIZATION_FF) {
                        assignedDao.delete(mcbBean.getLinkedAccountId(), targetYearMonth);
                    }
                    assignedDao.insert(applyList);
                }
            }, conditions);
        }

        // 返却内容の設定
        CompileInfoBean info = new CompileInfoBean();
        BeanUtil.copyProperties(info, input);
        CompileContainerBean<CompileInfoBean> output = new CompileContainerBean<>();
        output.setInfoBean(info);
        output.setProcessingResult(ProcessingResult.SUCCESS);
        return output;
    }

    /**
     * 読み込み区分を返却します。
     *
     * @param loopCount ループカウント
     * @return 読み込み区分
     */
    private ReadType getReadType(int loopCount) {
        ReadType readType = null;
        switch (loopCount) {
        case 0:
            readType = DaoReadTypeOfTotalization.TOTALIZATION_FF;
            break;
        case 1:
            readType = DaoReadTypeOfTotalization.TOTALIZATION_TF;
            break;
        case 2:
            readType = DaoReadTypeOfTotalization.TOTALIZATION_FT;
            break;
        case 3:
            readType = DaoReadTypeOfTotalization.TOTALIZATION_TT;
            break;
        default:
            // 通常発生しない。
            throw new CommonException("loop count fail");
        }
        return readType;
    }
}
